package myjava.l_reflect.reflect;

import java.lang.reflect.Field;

/**
 * @Auther: cty
 * @Date: 2020/2/19 13:58
 * @Description: 操作属性（字段）
 * 	一、获取类对象
 * 	二、获取属性对象
 * 		    getFields()					      获取 “类及其父类” 的 “所有” 公共属性	    返回Field[]
 * 		    getField(String name)			  获取 “类及其父类” 的 “指定” 公共属性	    返回Field
 * 		    getDeclaredFields()				  获取 “类” 的 “所有” 属性	(不包括父类)	    返回Field[]
 * 		    getDeclaredField(String name)	  获取 “类” 的 “指定” 属性(不包括父类)		返回Field
 * 	三、操作属性对象（设置和获取属性值）
 * 		    操作静态属性
 * 			    属性对象.get(null) 		  返回静态属性的值
 * 			    属性对象.set(null,"值")	  赋值
 * 		    操作非静态属性
 * 			    属性对象.get(Object obj);
 * 			    属性对象.set(Object obj,"值");
 *
 * @version: 1.0
 */
public class OperateField {
    public static void main(String[] args) {
        testField();
    }

    // 打印属性对象的修饰符、类型、属性名
    public static void printInfo(Field fd){
        // Field类常用方法
        System.out.println("获取修饰符-->"+fd.getModifiers());  // 每个修饰符对应一个数值，若有多个修饰符则返回数值之和，数值之和不会与修饰符的数值重复
        System.out.println("获取类型-->"+fd.getType());  // 返回一个 class对象或基本数据类型
        System.out.println("获取属性名-->"+fd.getName());  // 返回一个字符串
        System.out.println("-------------------------");
    }

    // 操作属性
    public static void testField(){
        try {
            // 一、获取类对象
            Class cla = Class.forName("com.cty.pojo.Student");

            // 二、获取属性对象
            System.out.println("2-1 获取 “类及其父类” 的 “所有” 公共属性");
            Field[] fds = cla.getFields();
            for(Field f : fds){
                printInfo(f);
            }
            System.out.println("**********************************************************");

            System.out.println("2-2 获取 “类及其父类” 的 “指定” 公共属性");
            Field fd = cla.getField("name");
            printInfo(fd);
            System.out.println("**********************************************************");

            System.out.println("2-3 获取 “类” 的 “所有” 属性（无法获取父类属性，但可以通过cla.getSuperclass()定位到父类再获取属性）");
            Field[] fds2 = cla.getDeclaredFields();
            for(Field f:fds2){
                printInfo(f);
            }
            System.out.println("**********************************************************");

            System.out.println("2-4 获取 “类” 的 “指定” 属性（无法获取父类属性，但可以通过cla.getSuperclass()定位到父类再获取属性）");
            Field f2 = cla.getDeclaredField("sno");
            printInfo(f2);

            // 三、操作属性对象（修改和获取属性值）
            System.out.println("3-1 操作静态属性值");
            //注意：不能操作private修饰的属性值；不能操作protected和default修饰但不在一个包内的属性值。
            Field fs = cla.getDeclaredField("isGraduate");
            fs.set(null,false);  // 设置静态属性值
            System.out.println(fs.get(null));  // 获取静态属性值
            System.out.println("**********************************************************");

            System.out.println("3-2 操作非静态属性值");
            Field fns = cla.getDeclaredField("sclass");
            Object obj = cla.newInstance();  // 获取实例对象
            fns.set(obj, "高三2班");  // 设置非静态属性值
            System.out.println(fns.get(obj));  // 获取非静态属性值
            System.out.println("**********************************************************");

            System.out.println("3-3 暴力反射操作没有访问权限的属性（不安全，不常用，了解）");
            Field fdForce = cla.getDeclaredField("inLove");
            fdForce.setAccessible(true);  // 暴力反射操作私有化属性
            Object objForce = cla.newInstance();  // 获取实例化对象
            System.out.println(fdForce.get(objForce));
            System.out.println("**********************************************************");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

/*
2-1 获取 “类及其父类” 的 “所有” 公共属性
获取修饰符-->1
获取类型-->class java.lang.String
获取属性名-->sno
-------------------------
获取修饰符-->1
获取类型-->class java.lang.String
获取属性名-->sclass
-------------------------
获取修饰符-->1
获取类型-->int
获取属性名-->sgroup
-------------------------
获取修饰符-->9
获取类型-->boolean
获取属性名-->isGraduate
-------------------------
获取修饰符-->1
获取类型-->class java.lang.String
获取属性名-->name
-------------------------
**********************************************************
2-2 获取 “类及其父类” 的 “指定” 公共属性
获取修饰符-->1
获取类型-->class java.lang.String
获取属性名-->name
-------------------------
**********************************************************
2-3 获取 “类” 的 “所有” 属性（无法获取父类属性，但可以通过cla.getSuperclass()定位到父类再获取属性）
获取修饰符-->1
获取类型-->class java.lang.String
获取属性名-->sno
-------------------------
获取修饰符-->1
获取类型-->class java.lang.String
获取属性名-->sclass
-------------------------
获取修饰符-->1
获取类型-->int
获取属性名-->sgroup
-------------------------
获取修饰符-->9
获取类型-->boolean
获取属性名-->isGraduate
-------------------------
获取修饰符-->2
获取类型-->boolean
获取属性名-->inLove
-------------------------
**********************************************************
2-4 获取 “类” 的 “指定” 属性（无法获取父类属性，但可以通过cla.getSuperclass()定位到父类再获取属性）
获取修饰符-->1
获取类型-->class java.lang.String
获取属性名-->sno
-------------------------
3-1 操作静态属性值
false
**********************************************************
3-2 操作非静态属性值
高三2班
**********************************************************
3-3 暴力反射操作没有访问权限的属性（不安全，不常用，了解）
false
**********************************************************
*/